package com.zf.gson;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.reflect.TypeToken;
import com.zf.gson.entity.Account;
import com.zf.gson.entity.ExposeObj;
import com.zf.gson.entity.RoleInfo;
import com.zf.gson.entity.UserInfo;
import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.List;

/**
 * Gson 的使用
 */
public class GsonTest {

    @Test
    void testSimpleJson() {
        // 创建 Gson 对象
        // Gson gson = new Gson();
        // 推荐使用 GsonBuilder 创建 Gson 对象，这样可以灵活的对Gson进行配置
        Gson gson = new GsonBuilder().create();
        Account account = new Account("123", "张三", "16666666666");

        // 对象转json
        String s = gson.toJson(account);
        System.out.println(s);

        String str = "{\"uid\":\"123\",\"userName\":\"张三\",\"telNumber\":\"55555\"}";
        // json转对象
        Account a1 = gson.fromJson(str, Account.class);
        System.out.println(a1);
    }

    /**
     * 泛型的转换
     */
    @Test
    void testGeneric() {
        Gson gson = new GsonBuilder().create();

        ArrayList<Account> accounts = new ArrayList<>();
        accounts.add(new Account("123", "张三", "16666666666"));
        accounts.add(new Account("345", "李四", "18888888888"));

        // 转json
        String json = gson.toJson(accounts);
        System.out.println(json);

        // json转最对象，由于java泛型的类型擦除，所以泛型要特殊处理，
        // 这里使用了匿名内部类，匿名内部类相当定义了一个类继承了TypeToken同时传入泛型参数，这样匿名类的定义中就有了泛型参数的具体类型了，可以在子类中获取定义中的父类的泛型参数的具体类型
        String str = "[{\"uid\":\"123\",\"userName\":\"张三\",\"telNumber\":\"16666666666\"},{\"uid\":\"345\",\"userName\":\"李四\",\"telNumber\":\"18888888888\"}]";
        List<Account> acs = gson.fromJson(str, new TypeToken<List<Account>>(){}.getType());
        System.out.println(acs);
    }


    /**
     * Expose注解
     */
    @Test
    void testAnno() {
        Gson gson = new GsonBuilder()
                // 使 Expose 注解生效，序列化和反序列化时忽略没有 Expose 注解的属性
                .excludeFieldsWithoutExposeAnnotation()
                .create();
        ExposeObj exposeObj = new ExposeObj("789", "wanger", "110");
        String json = gson.toJson(exposeObj);
        System.out.println(json);

        String str = "{\"uid\":\"789\",\"userName\":\"wanger\",\"telNumber\":\"110\", \"age\": 23}";
        ExposeObj obj = gson.fromJson(str, ExposeObj.class);
        System.out.println(obj);
    }

    /**
     * 序列化 null
     * 默认情况下：Gson不会把null属性序列化到json中
     */
    @Test
    void testNull() {
        Gson gson = new GsonBuilder().create();
        Account account = new Account(null, null, "333");
        String json = gson.toJson(account);
        System.out.println(json);

        Gson gs1 = new GsonBuilder()
                // 设置序列化 null 属性
                .serializeNulls()
                .create();
        String json1 = gs1.toJson(account);
        System.out.println(json1);
    }

    /**
     * 嵌套类型
     */
    @Test
    void testNest() {
        Gson gson = new GsonBuilder().create();

        RoleInfo roleInfo = new RoleInfo();
        roleInfo.setRoleName("角色1");
        roleInfo.setRoleId(1L);
        UserInfo userInfo = new UserInfo();
        userInfo.setUserId(1L);
        userInfo.setUsername("张三");
        userInfo.setAge(23);
        userInfo.setRoleInfo(roleInfo);

        String json = gson.toJson(userInfo);
        System.out.println(json);

        String str = "{\"userId\":1,\"username\":\"张三\",\"age\":23,\"roleInfo\":{\"roleId\":1,\"roleName\":\"角色1\"}}";
        UserInfo res = gson.fromJson(str, UserInfo.class);
        System.out.println(res);
    }
}
